观察者【Observer】

实例

  1. 被观察者:至少要实现实现Observable接口规定的attach()、detach()、notify()三个方法,用以添加、删除和通知观察者。
  2. 观察者:每个都必须实现Observer接口规定的update()方法
interface Observable
{
    public function attach(Observer $observer); // 添加
    public function detach(Observer $observer); // 删除
    public function notify(); // 触发通知
    public function getState(); // 获取状态
}
interface Observer
{
    public function update(Observable $observable);
}
/**
 * 被观察者
 * 职责:添加观察者到$observers属性中,
 * 有变动时通过notify()方法运行通知
 */
class Order implements Observable
{
    private $observers = []; // 保存观察者
    private $state = 0; // 订单状态
    // 添加(注册)观察者
    public function attach(Observer $observer)
    {
        $key = array_search($observer, $this->observers);
        if ($key === false) {
            $this->observers[] = $observer;
        }
    }
    // 移除观察者
    public function detach(Observer $observer)
    {
        $key = array_search($observer, $this->observers);
        if ($key !== false) {
            unset($this->observers[$key]);
        }
    }
    // 遍历调用观察者的update()方法进行通知,不关心其具体实现方式
    public function notify()
    {
        foreach ($this->observers as $observer) {
            // 把本类对象传给观察者,以便观察者获取当前类对象的信息
            $observer->update($this);
        }
    }
    // 订单状态有变化时发送通知
    public function addOrder()
    {
        $this->state = 1;
        $this->notify();
    }
    // 获取提供给观察者的状态
    public function getState()
    {
        return $this->state;
    }
}
class Email implements Observer
{
    public function update(Observable $observable)
    {
        $state = $observable->getState();
        if ($state) {
            echo '发送邮件:您已经成功下单。', PHP_EOL;
        } else {
            echo '发送邮件:下单失败,请重试。', PHP_EOL;
        }
    }
}
class Message implements Observer
{
    public function update(Observable $observable)
    {
        $state = $observable->getState();
        if ($state) {
            echo '短信通知:您已下单成功。', PHP_EOL;
        } else {
            echo '短信通知:下单失败,请重试。', PHP_EOL;
        }
    }
}
class Log implements Observer
{
    public function update(Observable $observable)
    {
        echo '记录日志:生成了一个订单记录。', PHP_EOL;
    }
}
$email = new Email(); // 创建Email观察者对象
$message = new Message(); // 创建Message观察者对象
$log = new Log(); // 创建Log观察者对象

$order = new Order(); // 创建订单对象

// 向订单对象中注册3个观察者:发送邮件、短信通知、记录日志
$order->attach($email);
$order->attach($message);
$order->attach($log);
$order->addOrder(); // 添加订单,添加时会自动发送通知给观察者

echo '====华丽的分隔符====', PHP_EOL;

$order->detach($log); // 删除记录日志观察者
$order->addOrder(); // 添加另一个订单,会再次发送通知给观察者

总结

观察者模式通过目标对象维护并自动通知所有依赖的观察者对象,建立了一对多、抽象耦合的订阅/发布机制,从而实现状态变化的广播通知

意图

定义对象间 “一对多”的依赖关系。当目标对象(Subject,又称被观察者)状态改变时,所有依赖的对象(Observer,又称观察者)都会被自动通知并更新。

主要解决

解决一个对象状态改变后,如何高效、低耦合地通知所有依赖对象的问题,建立广播通知机制。

何时使用

一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

如何解决

关键代码

在抽象类里有一个 ArrayList 存放观察者们。

优点

实现了对象间的低耦合;建立了一套触发机制

缺点

使用场景

注意事项